package com.peans.common.utils.mapBean;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Created by res-miaofeng on 2016/3/2.
 */
public final class MapBeanUtils {

	private static ObjectMapper mapper = new ObjectMapper();
	
    private MapBeanUtils(){

    }

    public static String toJson(MapBean bean){
        String result = null;
        try {
            result = mapper.writeValueAsString(bean);
        } catch (JsonProcessingException e) {
            //logger.error("转换失败！");
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解析（不支持嵌套,数组）
     * @param mapper
     * @param str
     * @return
     */
    public static MapBean parseJson(String str,BeanProperty[] array){
        MapBean result = null;
        try {
            if (str != null && str.length() > 0){
                result  = new MapBean();
                if (array != null && array.length > 0){
                    JsonNode rootNode = mapper.readTree(str);
                    for (int i = 0; i < array.length; i++) {
                        BeanProperty p = array[i];
                        setProperty(mapper,result,p,rootNode);
                    }
                }
            }
        } catch (IOException e) {
           // logger.error("转换失败，str:{}",str);
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 从map转换
     * @param maps
     * @param array
     * @return
     */
    public static MapBean convertFromMap(Map<String,String> maps,BeanProperty[] array){
        MapBean result = null;
        if (array != null && array.length > 0){
            result  = new MapBean();
            for (int i = 0; i < array.length; i++) {
                String value = maps.get(array[i].getName());
                if (StringUtils.isNotEmpty(value)){
                    setProperty(result,value,array[i]);
                }
            }
        }
        return result;
    }

    /**
     * 转成bean
     * @param type
     * @param mapBean
     * @return
     */
    public static <T> T toBean(Class<T> type, MapBean mapBean){
        T t = null;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
            t = type.newInstance(); // 创建 JavaBean 对象
            // 给 JavaBean 对象的属性赋值
            PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
            for (int i = 0; i< propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                Set<Map.Entry<BeanProperty, Object>> sets = mapBean.entrySet();
                for (Map.Entry<BeanProperty, Object> entry : sets){
                    BeanProperty b = entry.getKey();
                    if (b.getName().equals(propertyName)){
                        Object value = entry.getValue();
                        Object[] args = new Object[1];
                        args[0] = value;
                        descriptor.getWriteMethod().invoke(t, args);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return t;
    }


    public static MapBean convertFromBean(Object bean,BeanProperty[] array) {
        MapBean result = null;
        if (array != null && array.length > 0){
            result  = new MapBean();
            Class<?> type = bean.getClass();
            BeanInfo beanInfo = null;
            try {
                beanInfo = Introspector.getBeanInfo(type);
            } catch (IntrospectionException e) {
                e.printStackTrace();
            }
            if (beanInfo != null){
                PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
                for (int i = 0; i < array.length; i++) {
                    try {
                        for (int j = 0; j< propertyDescriptors.length; j++) {
                            PropertyDescriptor descriptor = propertyDescriptors[j];
                            String propertyName = descriptor.getName();
                            if (!propertyName.equals("class") && propertyName.equals(array[i].getName())) {
                                Method readMethod = descriptor.getReadMethod();
                                Object obj = readMethod.invoke(bean, new Object[0]);
                                result.add(array[i],obj);
                            }
                        }
                    }catch (Exception e){
                       // logger.error("转换失败，property:{}",p.getName());
                    }
                }
            }
        }
        return result;
    }


    private static void setProperty(MapBean bean,String value,BeanProperty p) {
        try {
            Class<?> type = p.getClassType();
            if (type.equals(String.class)){
                bean.add(p,value);
            }else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)){
                if (value.equals("1")){
                    bean.add(p,Boolean.TRUE);
                }else if (value.equals("0")){
                    bean.add(p,Boolean.FALSE);
                }
            }else if (type.equals(Integer.class) || type.equals(Integer.TYPE)){
                bean.add(p,Integer.valueOf(value));
            }else if (type.equals(Long.class) || type.equals(Long.TYPE)){
                bean.add(p,Long.valueOf(value));
            }else if (type.equals(Double.class) || type.equals(Double.TYPE)){
                bean.add(p,Double.valueOf(value));
            }else if (type.equals(Float.class) || type.equals(Float.TYPE)){
                bean.add(p,Float.valueOf(value));
            }else if (type.equals(BigDecimal.class)){
                BigDecimal t = new BigDecimal(value);
                bean.add(p,t);
            }else if (type.equals(byte[].class)){
                bean.add(p,value.getBytes());
            }else if (type.equals(Date.class)){
                Date date = new Date(Long.valueOf(value));
                bean.add(p,date);
            }
        } catch (Exception e) {
            //logger.error("转换失败，property:{}",p.getName());
            e.printStackTrace();
        }
    }


    private static void setProperty(ObjectMapper mapper,MapBean bean, BeanProperty p, JsonNode rootNode) {
        try {
            Class type = p.getClassType();
            String name = p.getName();
            JsonNode node = rootNode.get(name);
            if (node != null && !node.isNull()){
                if (type.equals(String.class)){
                    bean.add(p,node.textValue());
                }else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)){
                    bean.add(p,node.booleanValue());
                }else if (type.equals(Integer.class) || type.equals(Integer.TYPE)){
                    bean.add(p,node.intValue());
                }else if (type.equals(Long.class) || type.equals(Long.TYPE)){
                    bean.add(p,node.longValue());
                }else if (type.equals(Double.class) || type.equals(Double.TYPE)){
                    bean.add(p,node.doubleValue());
                }else if (type.equals(Float.class) || type.equals(Float.TYPE)){
                    bean.add(p,node.floatValue());
                }else if (type.equals(BigDecimal.class)){
                    BigDecimal t = (BigDecimal)node.numberValue();
                    bean.add(p,t);
                }else if (type.equals(byte[].class)){
                    bean.add(p,rootNode.get(name).binaryValue());
                }else if (type.equals(Date.class)){
                    DateFormat dateFormat = mapper.getSerializationConfig().getDateFormat();
                    Date date = dateFormat.parse(node.asText());
                    bean.add(p,date);
                }
                else {
                    String a = node.toString();
                    Object object = mapper.readValue(a, p.getClassType());
                    bean.add(p,object);
                }
            }
        } catch (Exception e) {
           // logger.error("转换失败，property:{}",p.getName());
            e.printStackTrace();
        }
    }




    /**
    private static void toJson(String content,ObjectMapper mapper,Object object){
        try {
            String str = mapper.writeValueAsString(object);
            content = content + str;
        } catch (JsonProcessingException e) {
            logger.error("转换失败！");
            e.printStackTrace();
        }
    }
     **/

}
